package com.iris.live.services.services.impl;

import com.iris.live.services.common.DateFormatUtils;
import com.iris.live.services.common.JPush;
import com.iris.live.services.common.StringUtils;
import com.iris.live.services.data.models.Lsh消息Model;
import com.iris.live.services.data.models.用户Model;
import com.iris.live.services.data.models.销售项目设置Model;
import com.iris.live.services.data.models.销售项目设置ModelPK;
import com.iris.live.services.data.repositories.Lsh消息Repository;
import com.iris.live.services.data.repositories.SalesClueSetRepository;
import com.iris.live.services.data.repositories.用户Repository;
import com.iris.live.services.data.repositories.销售项目设置Repository;
import com.iris.live.services.models.PageData;
import com.iris.live.services.models.ResultData;
import com.iris.live.services.services.SalesClueSetService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

/**
 * Created by lusong on 2017/6/30.
 */
@Service
@Component
public class SalesClueSetServiceImpl implements SalesClueSetService {

    private static Logger logger = LoggerFactory.getLogger(SalesClueSetServiceImpl.class);

    private static final String CLUE_SUPERIOR_LIMIT_NAME = "线索总数上限";
    private static final String CLUE_UNDER_LIMIT_NAME = "线索总数下限";
    private static final String RECEPTION_ARRANGE = "RECEPTION_ARRANGE";//高于未订单线索上限,该销售顾问无法进行展厅散客接待
    private static final String CDO_CLUE_ALLOCATION = "CDO_CLUE_ALLOCATION";//高于未订单线索上限,CDO无法分配线索到该销售顾问
    private static final String MGT_REDISTRIBUTION = "MGT_REDISTRIBUTION";//高于未订单线索上限,LiVE i-Mgt无法重新分配线索给该销售顾问
    private static final String CLUE_SUPERIOR_LIMIT_NUM = "120";//销售顾问线索上限默认 120
    private static final String CLUE_UNDER_LIMIT_NUM = "80";//销售顾问线索下限默认 80

    @Autowired
    private 销售项目设置Repository 销售项目设置Repository;

    @Autowired
    private SalesClueSetRepository salesClueSetRepository;

    @Autowired
    private 用户Repository 用户Repository;

    @Autowired
    private Lsh消息Repository lsh消息Repository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultData querySalesClueSetInfo(String permit, String username) throws Exception {
        ResultData resultData = new ResultData("false", null, null);
        Map<String, Object> mapValue = new HashMap<>();

        //查询 销售顾问线索上限
        销售项目设置ModelPK modelPK1 = new 销售项目设置ModelPK();
        销售项目设置Model model1 = null;
        modelPK1.set许可(permit);
        modelPK1.set设置项目(CLUE_SUPERIOR_LIMIT_NAME);
        model1 = 销售项目设置Repository.findOne(modelPK1);
        if (model1 == null) {
            model1 = saveSaleProjectSet(model1, permit, CLUE_SUPERIOR_LIMIT_NAME, CLUE_SUPERIOR_LIMIT_NUM, username);
            mapValue.put("clueSuperiorLimit", CLUE_SUPERIOR_LIMIT_NUM);
        } else {
            if (StringUtils.isNullOrBlank(model1.get值())) {
                model1 = saveSaleProjectSet(model1, permit, CLUE_SUPERIOR_LIMIT_NAME, CLUE_SUPERIOR_LIMIT_NUM, username);
            }
            mapValue.put("clueSuperiorLimit", model1.get值());
        }

        //查询 销售顾问线索下限
        销售项目设置ModelPK modelPK2 = new 销售项目设置ModelPK();
        销售项目设置Model model2 = null;
        modelPK2.set许可(permit);
        modelPK2.set设置项目(CLUE_UNDER_LIMIT_NAME);
        model2 = 销售项目设置Repository.findOne(modelPK2);
        if (model2 == null) {
            model2 = saveSaleProjectSet(model2, permit, CLUE_UNDER_LIMIT_NAME, CLUE_UNDER_LIMIT_NUM, username);
            mapValue.put("clueUnderLimit", CLUE_UNDER_LIMIT_NUM);
        } else {
            if (StringUtils.isNullOrBlank(model2.get值())) {
                model2 = saveSaleProjectSet(model2, permit, CLUE_UNDER_LIMIT_NAME, CLUE_UNDER_LIMIT_NUM, username);
            }
            mapValue.put("clueUnderLimit", model2.get值());
        }

        //查询 高于未订单线索上限,销售顾问 是否 无法进行 展厅散客接待
        销售项目设置ModelPK modelPK3 = new 销售项目设置ModelPK();
        销售项目设置Model model3 = null;
        modelPK3.set许可(permit);
        modelPK3.set设置项目(RECEPTION_ARRANGE);
        model3 = 销售项目设置Repository.findOne(modelPK3);
        if (model3 == null) {
            model3 = saveSaleProjectSet(model3, permit, RECEPTION_ARRANGE, "否", username);
            mapValue.put("receptionArrange", "否");
        } else {
            mapValue.put("receptionArrange", model3.get值());
        }

        //查询 高于未订单线索上限,LiVE i-Mgt 是否 无法重新分配线索给该销售顾问
        销售项目设置ModelPK modelPK4 = new 销售项目设置ModelPK();
        销售项目设置Model model4 = null;
        modelPK4.set许可(permit);
        modelPK4.set设置项目(MGT_REDISTRIBUTION);
        model4 = 销售项目设置Repository.findOne(modelPK4);
        if (model4 == null) {
            model4 = saveSaleProjectSet(model4, permit, MGT_REDISTRIBUTION, "否", username);
            mapValue.put("mgtRedistribution", "否");
        } else {
            mapValue.put("mgtRedistribution", model4.get值());
        }

        //查询 高于未订单线索上限,CDO 是否 无法分配线索到该销售顾问
        销售项目设置ModelPK modelPK5 = new 销售项目设置ModelPK();
        销售项目设置Model model5 = null;
        modelPK5.set许可(permit);
        modelPK5.set设置项目(CDO_CLUE_ALLOCATION);
        model5 = 销售项目设置Repository.findOne(modelPK5);
        if (model5 == null) {
            model5 = saveSaleProjectSet(model5, permit, CDO_CLUE_ALLOCATION, "否", username);
            mapValue.put("cdoClueAllocation", "否");
        } else {
            mapValue.put("cdoClueAllocation", model5.get值());
        }

        List list = new ArrayList();
        list.add(mapValue);
        resultData.setResult("true");
        resultData.setPageData(new PageData(list, 1));
        return resultData;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultData saveSalesClueSetInfo (String permit, String username, GetSaveSaleProjectSetParam getSaveSaleProjectSetParam)
            throws Exception {
        ResultData resultData = new ResultData("false", null, null);
        String clueSuperiorLimit = getSaveSaleProjectSetParam.clueSuperiorLimit,
                clueUnderLimit = getSaveSaleProjectSetParam.clueUnderLimit;
        //销售顾问 线索上限、线索下限 不能为空，否则抛出/返回错误信息
        if (StringUtils.isNullOrBlank(clueSuperiorLimit) || StringUtils.isNullOrBlank(clueUnderLimit)) {
            logger.error("销售顾问线索上限或下限为空");
            resultData.setMessage("销售顾问线索上限或下限不能为空");
            return resultData;
        } else {
            if ("0".equals(clueSuperiorLimit.substring(0,1)) || "0".equals(clueUnderLimit.substring(0,1))) {
                logger.error("销售顾问线索上限或下限为0或以0开头");
                resultData.setMessage("销售顾问线索上限或下限填写有误");
                return resultData;
            }
        }
        //销售顾问 线索上限不能小于线索下限，否则抛出/返回错误信息
        if (Integer.parseInt(clueSuperiorLimit) - Integer.parseInt(clueUnderLimit) < 0) {
            logger.error("销售顾问线索上限小于下限");
            resultData.setMessage("销售顾问线索上限不能小于下限");
            return resultData;
        }

        long model1TimeStart = DateFormatUtils.getCurrentTime();
        //保存 设置的销售顾问 线索上限
        销售项目设置Model model1 = saveSaleProjectSet(null, permit, CLUE_SUPERIOR_LIMIT_NAME, clueSuperiorLimit, username);
        long model1TimeEnd = DateFormatUtils.getCurrentTime() - model1TimeStart;
        if (model1 == null) {
            logger.error("销售顾问线索上限保存失败");
            resultData.setMessage("销售顾问线索上限保存失败");
            return resultData;
        }
        //保存 设置的销售顾问 线索下限
        long model2TimeStart = DateFormatUtils.getCurrentTime();
        销售项目设置Model model2 = saveSaleProjectSet(null, permit, CLUE_UNDER_LIMIT_NAME, clueUnderLimit, username);
        long model2TimeEnd = DateFormatUtils.getCurrentTime() - model2TimeStart;
        if (model2 == null) {
            logger.error("销售顾问线索下限保存失败");
            resultData.setMessage("销售顾问线索下限保存失败");
            return resultData;
        }
        //保存 销售顾问高于未订单线索上限,该销售顾问是否无法进行展厅散客接待
        long model3TimeStart = DateFormatUtils.getCurrentTime();
        if (!StringUtils.isNullOrBlank(getSaveSaleProjectSetParam.receptionArrange)) {
            销售项目设置Model model3 = saveSaleProjectSet(null, permit, RECEPTION_ARRANGE, getSaveSaleProjectSetParam.receptionArrange, username);
            if (model3 == null) {
                logger.error("高于未订单线索上限,该销售顾问是否无法进行展厅散客接待保存失败");
                resultData.setMessage("高于未订单线索上限,该销售顾问是否无法进行展厅散客接待保存失败");
                return resultData;
            }
        }
        long model3TimeEnd = DateFormatUtils.getCurrentTime() - model3TimeStart;
        //保存 销售顾问高于未订单线索上限,CDO是否无法分配线索到该销售顾问
        long model4TimeStart = DateFormatUtils.getCurrentTime();
        if (!StringUtils.isNullOrBlank(getSaveSaleProjectSetParam.cdoClueAllocation)) {
            销售项目设置Model model4 = saveSaleProjectSet(null, permit, CDO_CLUE_ALLOCATION, getSaveSaleProjectSetParam.cdoClueAllocation, username);
            if (model4 == null) {
                logger.error("高于未订单线索上限,CDO是否无法分配线索到该销售顾问保存失败");
                resultData.setMessage("高于未订单线索上限,CDO是否无法分配线索到该销售顾问保存失败");
                return resultData;
            }
        }
        long model4TimeEnd = DateFormatUtils.getCurrentTime() - model4TimeStart;
        //保存 销售顾问高于未订单线索上限,LiVE i-Mgt是否无法重新分配线索给该销售顾问
        long model5TimeStart = DateFormatUtils.getCurrentTime();
        if (!StringUtils.isNullOrBlank(getSaveSaleProjectSetParam.mgtRedistribution)) {
            销售项目设置Model model5 = saveSaleProjectSet(null, permit, MGT_REDISTRIBUTION, getSaveSaleProjectSetParam.mgtRedistribution, username);
            if (model5 == null) {
                logger.error("高于未订单线索上限,LiVE i-Mgt是否无法重新分配线索给该销售顾问保存失败");
                resultData.setMessage("高于未订单线索上限,LiVE i-Mgt是否无法重新分配线索给该销售顾问保存失败");
                return resultData;
            }
        }
        long model5TimeEnd = DateFormatUtils.getCurrentTime() - model5TimeStart;

        String type = "线索";
        //查询出所有的线索超过上限的销售顾问
        //发送信息给销售顾问
        String exceedingTheLimitMessage = "您目前线索已经达到上限,请及时跟进名下线索。";
        List exceedingTheLimitList = salesClueSetRepository.queryExceedingTheTimitOgSales(permit, model1.get值());
        long model6TimeStart = DateFormatUtils.getCurrentTime();
        sendMessageToITask(permit, username, type, exceedingTheLimitMessage, exceedingTheLimitList);
        long model6TimeEnd = DateFormatUtils.getCurrentTime() - model6TimeStart;

        //查询出所有的线索未达到下限的销售顾问
        //发送消息给销售经理
        List belowTheLimitList = salesClueSetRepository.queryBelowTheLimitOfSales(permit, model2.get值());
        long model7TimeStart = DateFormatUtils.getCurrentTime();
        sendMessageToIMgt(permit, username, type, belowTheLimitList);
        long model7TimeEnd = DateFormatUtils.getCurrentTime() - model7TimeStart;

        resultData.setResult("true");
        System.out.println("保存 设置的销售顾问上限花费：" + model1TimeEnd);
        System.out.println("保存 设置的销售顾问下限花费：" + model2TimeEnd);
        System.out.println("保存 设置的销售顾问散客接待花费：" + model3TimeEnd);
        System.out.println("保存 设置的销售顾问分配线索花费：" + model4TimeEnd);
        System.out.println("保存 设置的销售顾问重新分配线花费：" + model5TimeEnd);
        System.out.println("保存 设置的销售顾问itask消息花费：" + model6TimeEnd);
        System.out.println("保存 设置的销售顾问imgt消息花费：" + model7TimeEnd);
        return resultData;
    }

    //发送信息给销售顾问
    @Async
    private void sendMessageToITask (String permit, String username, String type, String exceedingTheLimitMessage,List exceedingTheLimitList) {
        if (exceedingTheLimitList != null && !exceedingTheLimitList.isEmpty()) {
            List recUserList = new ArrayList();
            List<Lsh消息Model> lsh消息Models = new ArrayList<>();
            for (Object o : exceedingTheLimitList) {
                Map map = (Map) o;
                if (StringUtils.isNullOrBlank(map.get("scCode"))) {
                    logger.warn("销售顾问线索量设置--超过上限的销售顾问code为空");
                    continue;
                }
                String scCode = map.get("scCode").toString();
                Lsh消息Model lsh消息Model = getMessageModel(permit, username, permit, scCode, type, exceedingTheLimitMessage, username, null);
                recUserList.add(scCode);
                lsh消息Models.add(lsh消息Model);
            }
            JPush.sendPushForAndroidAndIos(exceedingTheLimitMessage, exceedingTheLimitMessage, null, recUserList, JPush.Platforms.iTask);
            lsh消息Repository.save(lsh消息Models);
        }
    }

    //发送信息给销售经理
    @Async
    private void sendMessageToIMgt (String permit, String username, String type, List belowTheLimitList) {
        if (belowTheLimitList != null && !belowTheLimitList.isEmpty()) {
            Map<String, String> belowTheLimitMap = new HashMap<>();
            List<Lsh消息Model> lsh消息Models = new ArrayList<>();
            for (Object o : belowTheLimitList) {
                Map map = (Map) o;
                if (StringUtils.isNullOrBlank(map.get("scCode"))) {
                    logger.warn("销售顾问线索量设置--低于下限的销售顾问code为空");
                    continue;
                }
                if (StringUtils.isNullOrBlank(map.get("scName"))) {
                    logger.warn("销售顾问线索量设置--低于下限的销售顾问姓名为空");
                    continue;
                }
                String scCode = map.get("scCode").toString();
                String scName = map.get("scName").toString();
                用户Model 用户Model = 用户Repository.findByCode(scCode);
                if (用户Model != null && !StringUtils.isNullOrBlank(用户Model.getSuperior())) {
                    if (!StringUtils.isNullOrBlank(belowTheLimitMap.get(用户Model.getSuperior()))) {
                        belowTheLimitMap.put(用户Model.getSuperior(), belowTheLimitMap.get(用户Model.getSuperior()) + "," + scName);
                    } else {
                        belowTheLimitMap.put(用户Model.getSuperior(), scName);
                    }
                }
            }
            for (String key : belowTheLimitMap.keySet()) {
                String belowTheLimiMessage = belowTheLimitMap.get(key) + "销售顾问目前线索总数已经低于设置下限,建议您在工作-进店线索重新分配中为销售顾问增加线索";
                List list = new ArrayList();
                list.add(key);
                JPush jPush = new JPush();
                jPush.sendPushForAndroidAndIos(belowTheLimiMessage, belowTheLimiMessage, null, list, JPush.Platforms.iMgt);
                Lsh消息Model lsh消息Model = getMessageModel(permit, username, permit, key, type, belowTheLimiMessage, username, null);
                lsh消息Models.add(lsh消息Model);
            }
            lsh消息Repository.save(lsh消息Models);
        }
    }

    /**
     * 保存并获取  销售项目设置model
     * @param model
     * @param permit
     * @param type
     * @param value
     * @param username
     * @return
     */
    private 销售项目设置Model saveSaleProjectSet(销售项目设置Model model, String permit, String type, String value, String username) {
        if (model == null) {
            model = new 销售项目设置Model();
        }
        if (!StringUtils.isNullOrBlank(permit)) {
            model.set许可(permit);
        }
        if (!StringUtils.isNullOrBlank(type)) {
            model.set设置项目(type);
        }
        if (!StringUtils.isNullOrBlank(value)) {
            model.set值(value);
        }
        if (!StringUtils.isNullOrBlank(username)) {
            model.set更新账号(username);
        }
        model.set更新时间(new Timestamp(new Date().getTime()));
        return 销售项目设置Repository.save(model);
    }

    /**
     * 获取 消息model
     * @param sendUser      发送人
     * @param sendPermit    发送许可
     * @param recPermit     接收许可
     * @param recUser       接收人
     * @param msgType       消息类型
     * @param content       消息文本
     * @param updateUser    修改人
     * @param mobile        电话号码
     * @return
     */
    private Lsh消息Model getMessageModel (String sendUser, String sendPermit, String recPermit, String recUser, String msgType,
                                        String content, String updateUser, String mobile) {
        Lsh消息Model l = new Lsh消息Model();
        l.set发送人(sendUser);
        l.set发送许可(sendPermit);
        l.set接收许可(recPermit);
        l.set接收人(recUser);
        l.set消息分类(msgType);
        l.set消息内容(content);
        l.set是否删除("否");
        l.set更新账号(updateUser);
        l.set消息创建时间(new Timestamp(new Date().getTime()));
        l.set更新时间(new Timestamp(new Date().getTime()));
        l.set电话号码(mobile);
        l.setRead(false);
        return l;
    }

    @Override
    public ResultData judgeSalesClueNumToSuperiorLimit (String permit, String username) throws Exception {
        ResultData resultData = new ResultData("fasle", null, null);
        //校验销售顾问 是否存在、是否已删除、是否离职
        用户Model 用户Model = 用户Repository.findByCode(username);
        if (用户Model == null) {
            logger.error("排班接待--账号:" + username + ",销售顾问不存在");
            resultData.setMessage("排班接待--账号:" + username + ",销售顾问不存在");
            return resultData;
        }
        if ("已删除".equals(用户Model.get删除状态())) {
            logger.error("排班接待--账号:" + username + ",销售顾问已删除");
            resultData.setMessage("排班接待--账号:" + username + ",销售顾问已删除");
            return resultData;
        }
        if ("离职".equals(用户Model.get销售顾问职位状态())) {
            logger.error("排班接待--账号:" + username + ",销售顾问已离职");
            resultData.setMessage("排班接待--账号:" + username + ",销售顾问已离职");
            return resultData;
        }
        //查询 经销商是否设置 高于未订单线索上限,该销售顾问无法进行展厅散客接待
        //如果未设置 则 销售顾问不需要考虑 线索上限 的问题
        销售项目设置ModelPK modelPK1 = new 销售项目设置ModelPK();
        modelPK1.set许可(permit);
        modelPK1.set设置项目(RECEPTION_ARRANGE);
        销售项目设置Model model1 = 销售项目设置Repository.findOne(modelPK1);
        if (model1 == null || "否".equals(model1.get值())) {
            resultData.setResult("true");
            return resultData;
        }
        List list = salesClueSetRepository.querySalesClueNum(permit, username);
        if (list != null && !list.isEmpty()) {
            int clueSuperiorLimitNum = 0;
            销售项目设置ModelPK 销售项目设置ModelPK = new 销售项目设置ModelPK();
            销售项目设置ModelPK.set许可(permit);
            销售项目设置ModelPK.set设置项目(CLUE_SUPERIOR_LIMIT_NAME);
            销售项目设置Model 销售项目设置Model = 销售项目设置Repository.findOne(销售项目设置ModelPK);
            if (销售项目设置Model == null || StringUtils.isNullOrBlank(销售项目设置Model.get值())) {
                clueSuperiorLimitNum = Integer.parseInt(CLUE_SUPERIOR_LIMIT_NUM);
            } else {
                clueSuperiorLimitNum = Integer.parseInt(销售项目设置Model.get值());
            }
            Map map = (Map) list.get(0);
            if (map != null && !StringUtils.isNullOrBlank(map.get("counts"))) {
                if (clueSuperiorLimitNum > Integer.parseInt(map.get("counts").toString())) {
                    resultData.setResult("true");
                } else {
                    resultData.setMessage("销售顾问名下线索数已经超过设置上限,暂不能出现在排班表中");
                }
            } else {
                logger.error("排班接待--校验销售顾问是否达到线索上限，查询结果有误");
                resultData.setMessage("排班接待--校验销售顾问是否达到线索上限，查询结果有误");
            }
        } else {
            logger.error("排班接待--校验销售顾问是否达到线索上限，未查询到相关销售顾问信息");
            resultData.setMessage("排班接待--校验销售顾问是否达到线索上限，未查询到相关销售顾问信息");
        }
        return resultData;
    }

    @Override
    public List querySalesClueNumUnderSuperiorLimit(String permit, String currentSC, String type) throws Exception {
        List list = null;
        //type = MGT 查询 经销商是否设置 高于未订单线索上限,LiVE i-Mgt无法重新分配线索给该销售顾问
        //type = CDO 查询 经销商是否设置 高于未订单线索上限,CDO无法分配线索到该销售顾问
        //如果未设置 则 销售顾问不需要考虑 线索上限 的问题
        销售项目设置ModelPK modelPK1 = new 销售项目设置ModelPK();
        modelPK1.set许可(permit);
        if ("MGT".equals(type)) {
            modelPK1.set设置项目(MGT_REDISTRIBUTION);
        } else if ("CDO".equals(type)) {
            modelPK1.set设置项目(CDO_CLUE_ALLOCATION);
        }
        销售项目设置Model model1 = 销售项目设置Repository.findOne(modelPK1);
        if (model1 == null || "否".equals(model1.get值())) {
            list = salesClueSetRepository.querySalesClueNum(permit, null);
        } else {
            销售项目设置ModelPK modelPK = new 销售项目设置ModelPK();
            modelPK.set许可(permit);
            modelPK.set设置项目(CLUE_SUPERIOR_LIMIT_NAME);
            销售项目设置Model model = 销售项目设置Repository.findOne(modelPK);
            String clueSuperiorLimit = null;
            if (model != null && !StringUtils.isNullOrBlank(model.get值())) {
                clueSuperiorLimit = model.get值();
            } else {
                clueSuperiorLimit = CLUE_SUPERIOR_LIMIT_NUM;
            }
            list = salesClueSetRepository.queryFailToReachTheTeilingOfSales(permit, clueSuperiorLimit, currentSC);
        }
        return list;
    }
}
